﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using IWshRuntimeLibrary;
using File = System.IO.File;

namespace Foundation
{
    public static class Link
    {
        public enum Kind
        {
            Shortcut,
            UrlShortcut,
            RegistryValue,
        }

        public const string ShortcutExtension = ".lnk";
        public const string UrlShortcutExtension = ".url";

        public static readonly WshShell WhsShell = new WshShell();

        public static bool Exists(Kind kind, string path, string target)
        {
            switch (kind)
            {
                case Kind.Shortcut:
                    if (!File.Exists(path)) return false;
                    var shortcut = (IWshShortcut) WhsShell.CreateShortcut(path);
                    var exists = Equals(shortcut.TargetPath, target);
                    Marshal.ReleaseComObject(shortcut);
                    return exists;
                case Kind.UrlShortcut:
                    if (!File.Exists(path)) return false;
                    var urlShortcut = (IWshURLShortcut) WhsShell.CreateShortcut(path);
                    exists = Equals(urlShortcut.TargetPath, target);
                    Marshal.ReleaseComObject(urlShortcut);
                    return exists;
                case Kind.RegistryValue:
                    if (!KeyExists(path)) return false;
                    var value = WhsShell.RegRead(path);
                    return Equals(value, target);
                default:
                    return false;
            }
        }

        public static void Create(Kind kind, string path, string target)
        {
            switch (kind)
            {
                case Kind.Shortcut:
                    var shortcut = (IWshShortcut) WhsShell.CreateShortcut(path);
                    shortcut.TargetPath = target;
                    shortcut.Save();
                    Marshal.ReleaseComObject(shortcut);
                    return;
                case Kind.UrlShortcut:
                    var urlShortcut = (IWshShortcut) WhsShell.CreateShortcut(path);
                    urlShortcut.TargetPath = target;
                    urlShortcut.Save();
                    Marshal.ReleaseComObject(urlShortcut);
                    return;
                case Kind.RegistryValue:
                    WhsShell.RegWrite(path, target);
                    return;
            }
        }

        public static void Delete(Kind kind, string path, string targetPath)
        {
            switch (kind)
            {
                case Kind.Shortcut:
                    if (!File.Exists(path)) return;
                    var shortcut = (IWshShortcut) WhsShell.CreateShortcut(path);
                    var equals = Equals(shortcut.TargetPath, targetPath);
                    if (equals && File.Exists(path))
                        File.Delete(path);
                    Marshal.ReleaseComObject(shortcut);
                    return;
                case Kind.UrlShortcut:
                    if (!File.Exists(path)) return;
                    var urlShortcut = (IWshURLShortcut) WhsShell.CreateShortcut(path);
                    var isCurrent = Equals(urlShortcut.TargetPath, targetPath);
                    if (isCurrent && File.Exists(path))
                        File.Delete(path);
                    Marshal.ReleaseComObject(urlShortcut);
                    return;
                case Kind.RegistryValue:
                    if (!KeyExists(path)) return;
                    WhsShell.RegDelete(Path.Combine(path, targetPath));
                    return;
            }
        }

        private static bool KeyExists(string path)
        {
            try
            {
                WhsShell.RegRead(path);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
